/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						      resource_file_dir.h

	$Header: /resource_editor/resource_file_dir.h $

	$NoKeywords: $

 ************************************************************************/

#ifndef RESOURCE_FILE_DIR_H_INCLUDED
#define RESOURCE_FILE_DIR_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#pragma warning( disable: 4786 )

#include <list>
#include <string>
#include <time.h>
#include <vector>
#include "resource_datatypes.h"
#include "sized_int_types.h"

// --------------------------------------------------------------------------------
// file header for a resource
// --------------------------------------------------------------------------------
struct t_resource_dir_entry
{
	t_resource_dir_entry();

    int         data_position;
    long        file_time;
    std::string name;
    std::string directory;
	std::string aliased_name; // if not empty, this entry is an alias for another entry.
	t_int32		data_type;

	int      get_length() const;
	t_uint32 get_uncompressed_size() const;
	void     set_length( int length );
	void     set_uncompressed_size( t_uint32 size );
	
	t_resource_dir_entry&       operator=( t_resource_dir_entry const & other );

private:

	int         m_length;
	t_uint32    m_uncompressed_size;
};

inline t_resource_dir_entry::t_resource_dir_entry()
{
	data_position		=0;
	file_time			=0;
	data_type			=k_medium_compression_binary;
	m_length			=0;
	m_uncompressed_size	=0;
}

inline int t_resource_dir_entry::get_length() const
{
	return m_length;
}

inline t_uint32 t_resource_dir_entry::get_uncompressed_size() const
{
	return m_uncompressed_size;
}

inline void t_resource_dir_entry::set_length( int length )
{
	m_length = length;
}

inline void t_resource_dir_entry::set_uncompressed_size( t_uint32 size )
{
	m_uncompressed_size = size;
}

inline t_resource_dir_entry& t_resource_dir_entry::operator=( t_resource_dir_entry const & other )
{
	data_position	= other.data_position;
	file_time		= other.file_time;
	name			= other.name;
	directory		= other.directory;
	aliased_name	= other.aliased_name;
	data_type		= other.data_type;
	m_length		= other.get_length();
	m_uncompressed_size = other.get_uncompressed_size();

	return *this;
}

// --------------------------------------------------------------------------------
// object to read & write resource file directories.  Designed to be shared between
// game and resource editor.
// --------------------------------------------------------------------------------
class t_resource_file_dir
{
public:
    static int const k_version;

	t_resource_file_dir();

    void add( t_resource_dir_entry& entry );
    void clear();
    int  get_size() const;
    int  get_version() const;
    bool read( std::streambuf& buffer );
	void remove( std::string const& name );
	void rename( std::string const& old_name, std::string const& new_name );
	void update( t_resource_dir_entry const& entry );
	bool write( std::streambuf& buffer );
	bool write( std::streambuf& buffer, t_resource_dir_entry& entry, std::string const& data );

	t_resource_dir_entry&       operator[]( int arg );
	t_resource_dir_entry const& operator[]( int arg ) const;
protected:
	// header for an empty block
	struct t_empty_block
	{
		int start;
		int length;
	};

	int  allocate( int size ); // find a block of a given size and allocate it
	void allocate( int start, int size ); // allocate a specific block
	void dispose( int start, int length ); // free a specific block

	int                               m_directory_start;
	int                               m_directory_length;
    int                               m_version;
    std::vector<t_resource_dir_entry> m_directory;
	std::list<t_empty_block>          m_empty_blocks;
};

// --------------------------------------------------------------------------------
// inlines for resource file directory
// --------------------------------------------------------------------------------
inline int t_resource_file_dir::get_size() const
{
    return m_directory.size();
}

inline int t_resource_file_dir::get_version() const
{
    return m_version;
}

inline t_resource_dir_entry& t_resource_file_dir::operator[]( int arg )
{
	return m_directory[arg];
}

inline t_resource_dir_entry const& t_resource_file_dir::operator[]( int arg ) const
{
	return m_directory[arg];
}

#endif // RESOURCE_FILE_DIR_H_INCLUDED